﻿using System;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SoccerSimulator5000
{
    public partial class SimMatchForm : Form
    {

        public int round { get; set; }
        public int matchNumber { get; set; }
        public Match match;


        private Button buttonStart = new Button();
        private RadioButton slowRadio = new RadioButton();
        private RadioButton mediumRadio = new RadioButton();
        private RadioButton fastRadio = new RadioButton();
        private RadioButton ultraRadio = new RadioButton();
        private RadioButton devRadio = new RadioButton();

        public SimMatchForm( int round, int matchNumber )
        {
            InitializeComponent();
            this.FormBorderStyle = FormBorderStyle.FixedDialog;
            this.round = round;
            this.matchNumber = matchNumber;

            buttonStart.Location = new Point(50, 500);
            buttonStart.Size = new Size(100, 50);
            buttonStart.Text = "Start";
            buttonStart.Click += new EventHandler(this.buttonStart_Click);
            this.Controls.Add(buttonStart);

            slowRadio.Location = new Point(200, 500);
            slowRadio.Text = "Slow Speed";
            this.Controls.Add(slowRadio);

            mediumRadio.Location = new Point(320, 500);
            mediumRadio.Text = "Medium Speed";
            this.Controls.Add(mediumRadio);

            fastRadio.Location = new Point(440, 500);
            fastRadio.Text = "Fast Speed";
            this.Controls.Add(fastRadio);

            ultraRadio.Location = new Point(560, 500);
            ultraRadio.Text = "Ultra Speed";
            this.Controls.Add(ultraRadio);

            devRadio.Location = new Point(560, 550);
            devRadio.Text = "Dev Speed";
            this.Controls.Add(devRadio);

            switch (Game.previousSimSpeed)
            {
                case 1:
                    slowRadio.Checked = true;
                    break;
                case 2:
                    mediumRadio.Checked = true;
                    break;
                case 3:
                    fastRadio.Checked = true;
                    break;
                case 4:
                    ultraRadio.Checked = true;
                    break;
                case 5:
                    devRadio.Checked = true;
                    break;
            }



            //eventsListBox.DataSource = Game.season.seasonFixtures.fixtures[round].round[match].commentaryList;
        }

        
        private void SimMatchForm_Paint(object sender, PaintEventArgs e)
        {
            Game.season.seasonFixtures.fixtures[round].round[matchNumber].Draw(20, 50, e.Graphics);
            e.Graphics.DrawString(match.attendance.ToString(), new System.Drawing.Font(System.Drawing.FontFamily.GenericSansSerif, 12), System.Drawing.Brushes.Black, new Point(350, 20));
        }

        private async void buttonStart_Click(object sender, EventArgs e)
        {
            if (slowRadio.Checked)
            {
                Game.previousSimSpeed = 1;
                buttonStart.Enabled = false;
                slowRadio.Enabled = false;
                mediumRadio.Enabled = false;
                fastRadio.Enabled = false;
                ultraRadio.Enabled = false;
                devRadio.Enabled = false;

                await PlayMatch(match, 1000);
            }
            else if (mediumRadio.Checked)
            {
                

                Game.previousSimSpeed = 2;
                buttonStart.Enabled = false;
                slowRadio.Enabled = false;
                mediumRadio.Enabled = false;
                fastRadio.Enabled = false;
                ultraRadio.Enabled = false;
                devRadio.Enabled = false;

                await PlayMatch(match, 750);
            }
            else if (fastRadio.Checked)
            {

                Game.previousSimSpeed = 3;
                buttonStart.Enabled = false;
                slowRadio.Enabled = false;
                mediumRadio.Enabled = false;
                fastRadio.Enabled = false;
                ultraRadio.Enabled = false;
                devRadio.Enabled = false;

                await PlayMatch(match, 500);
            }
            else if (ultraRadio.Checked)
            {
                Game.previousSimSpeed = 4;
                buttonStart.Enabled = false;
                slowRadio.Enabled = false;
                mediumRadio.Enabled = false;
                fastRadio.Enabled = false;
                ultraRadio.Enabled = false;
                devRadio.Enabled = false;

                await PlayMatch(match, 250);
            }
            else if (devRadio.Checked)
            {

                Game.previousSimSpeed = 5;
                buttonStart.Enabled = false;
                slowRadio.Enabled = false;
                mediumRadio.Enabled = false;
                fastRadio.Enabled = false;
                ultraRadio.Enabled = false;
                devRadio.Enabled = false;

                await PlayMatch(match, 0);
            }
            else
            {
                MessageBox.Show("Please Choose a simulation speed for this match", "Choose Speed");
            }

            
            
            this.Invalidate();
        }


        public void AddComment(string comment)
        {
            eventsListBox.Items.Add(new CommentaryRow(comment));
            eventsListBox.DisplayMember = "comment";

            eventsListBox.TopIndex = eventsListBox.Items.Count - 1;
            this.Invalidate();

        }

        public async Task PlayMatch( Match match, int speed)
        {
            match.CalculateAttendance();

            // Calculate the total possession and each teams percentage of possession.
            // Home team gets +10 to their midfieldScore to represent the "homefield-advantage"
            float posessionTotal = (match.awayTeam.teamData.midfieldScore + 5) + match.homeTeam.teamData.midfieldScore;
            float homeTeamPosession = (match.homeTeam.teamData.midfieldScore + 5) / posessionTotal;
            float awayTeamPosession = match.awayTeam.teamData.midfieldScore / posessionTotal;


            // Decide the total number of attack opportunities that occur during the duration of the match.
            // Also decide the duration of the match.
            int totalAdvanceOpportunities = Game.random.Next(35, 55);
            int matchDuration = Game.random.Next(90, 96);

            // Crate an array and populate it with the timestamp of each attack opportunity.
            int tempMinute;
            System.Collections.ArrayList advanceMinutes = new System.Collections.ArrayList();

            for (int i = 0; i < totalAdvanceOpportunities; i++)
            {
                // The do-while loop randomly draw a "minute" from the pool of matchduration minutes.
                // It continues to draw a new minute if the drawn number already exists in the arraylist.
                // This ensures that no two attack opportunities can occur on the same minute. Good or bad is for someone else to decide.
                do
                {
                    tempMinute = Game.random.Next(1, matchDuration + 1);
                }
                while (advanceMinutes.Contains(tempMinute));

                advanceMinutes.Add(tempMinute);
            }

            // Sort the arraylist so that the attack opportunities can occur in chronological order.
            advanceMinutes.Sort();

            foreach (var minute in advanceMinutes)
            {
                String comment = "";

                await Task.Delay(speed);


                int randomPossession = Game.random.Next(0, 100);

                if (randomPossession < (homeTeamPosession * 100))
                {
                    //Home Team attacks
                    comment += minute.ToString() + " " + match.homeTeam.name + " attempts to advance";
                    AddComment(comment);
                    await SimulateAdvance(match.homeTeam, match.awayTeam, minute, speed);
                }
                else
                {
                    // Away Team attacks
                    comment += minute.ToString() + " " + match.awayTeam.name + " attempts to advance";
                    AddComment(comment);
                    await SimulateAdvance(match.awayTeam, match.homeTeam, minute, speed);

                }
            }
            AddComment("Full Time");


            if (match.homeGoals > match.awayGoals)
            {
                match.homeTeamWin = true;
                match.awayTeamWin = false;
            }
            else if (match.awayGoals > match.homeGoals)
            {
                match.awayTeamWin = true;
                match.homeTeamWin = false;
            }
            else
            {
                match.awayTeamWin = true;
                match.homeTeamWin = true;
            }
            match.AppointPoints();
            match.homeTeam.finance.AddMatchIncome( match.attendance );
            Game.currentRound++;
        }

        public async Task SimulateAdvance(Team attacking, Team defending, object minute, int speed)
        {
            await Task.Delay(speed);
            // Determine attack% of attacking team and defend% of defending team.
            float totalPool = attacking.teamData.forwardScore + (defending.teamData.defenderScore + (defending.teamData.midfieldScore / 2) + (defending.teamData.forwardScore / 3));
            float attackingRange = attacking.teamData.forwardScore / totalPool;
            float defendingRange = (defending.teamData.defenderScore + (defending.teamData.midfieldScore / 2) + (defending.teamData.forwardScore / 3)) / totalPool;
            string comment = "";

            // Checks to see if advance is successful
            int randomRange = Game.random.Next(0, 100);
            // If number is in attackingAttack range - advance is successful.
            if (randomRange < (attackingRange * 100))
            {
                // Successful advance
                comment += minute.ToString() + " They move the ball up and attempts to score and... ";
                AddComment(comment);
                await SimulateAttack(attacking, defending, minute, speed);
            }
            else
            {
                comment += minute.ToString() + " but " + defending.name + " defends nicely";
                // Successful defending.
                // go back to simulating next advance
                AddComment(comment);
            }

        }

        public async Task SimulateAttack(Team attacking, Team defending, object minute, int speed)
        {
            await Task.Delay(speed);
            // Determine new attack% of attacking team and defend% of defending team.
            float totalPool = (attacking.teamData.forwardScore / 2) + (defending.teamData.goalieScore + (defending.teamData.defenderScore / 2) + (defending.teamData.midfieldScore / 3) + (defending.teamData.forwardScore / 4));
            float attackingRange = (attacking.teamData.forwardScore / 2) / totalPool;
            float defendingRange = (defending.teamData.goalieScore + (defending.teamData.defenderScore / 2) + (defending.teamData.midfieldScore / 3) + (defending.teamData.forwardScore / 4)) / totalPool;
            string comment = "";

            // Check to see if attack is successful ( goal is scored )
            int randomRange = Game.random.Next(0, 100);

            if (randomRange < (attackingRange * 100))
            {
                comment += minute.ToString() + " It's a goal!";
                AddComment(comment);
                if (attacking.name == match.homeTeam.name)
                    match.homeGoals++;
                else
                    match.awayGoals++;
            }
            else
            {
                comment += minute.ToString() + " The keeper somehow got to it!";
                AddComment(comment);
                // Goal is stopped
            }

        }


    }
}
